#ifndef STRAY_RESOURCE_SMD_H
#define STRAY_RESOURCE_SMD_H

#include <Misc/Delegate.h>
#include "../ResourceFile.h"
#include "../ResFileData.h"
#include "SMD.h"
#include "../../Resource/Mesh/MeshFactory.h"
#include "../../Resource/Material/MaterialFactory.h"
#include "../../Resource/Texture/TextureFactory.h"

namespace Stray {
namespace Resource {

class SmdFile : public ResourceFile
{
public:
	SmdFile(const FileID& fileName);
	SmdFile(const FileID& fileName, const Stray::Core::FileStream::ByteArray& fileData);

	void loadData();
	void writeData(const ResFileDataPtr& spResouces);

	ResFileDataPtr getResources() const;
private:
	ResFileDataPtr spResources_;
	SMD *pSmd_;

	MeshFactory meshFactory_;
	MaterialFactory materialFactory_;

	Stray::String readElementId(void* p) const;
	void readHeader(SMD_HEADER& refOutput, const Uint8* basePtr);
	void decodeSmd(SMD* pSmd, const Uint8* basePtr);
	void decodeDataArray(SMD_DATA_ARRAY* pDataArray, const Uint8* basePtr);

	void decodeMeshesLib(SMD_LIB_MESHES* pSmdMeshesLib, const Uint8* basePtr);
	void decodeMesh(SMD_MESH* pMesh, const Uint8* basePtr);
	void decodeVertices(SMD_VERTICES* pVertices, const Uint8* basePtr);
	void decodeTriangles(SMD_TRIANGLES* pTriangles, const Uint8* basePtr);
	void decodeSubset(SMD_SUBSET* pSubset, const Uint8* basePtr);

	void decodeMaterialsLib(SMD_LIB_MATERIALS* pMaterialsLib, const Uint8* basePtr);
	void decodeMaterial(SMD_MATERIAL* pMaterial, const Uint8* basePtr);
	void decodeMaterialParams(SMD_MATERIAL_PARAMS* pMaterialParams, const Uint8* basePtr);

	void decodeImagesLib(SMD_LIB_IMAGES* pImagesLib, const Uint8* basePtr);
	void decodeImage(SMD_IMAGE* pImage, const Uint8* basePtr);

	void decodeControllersLib(SMD_LIB_CONTROLLERS* pControllersLib, const Uint8* basePtr);
	void decodeController(SMD_CONTROLLER* pController, const Uint8* basePtr);
	void decodeSkin(SMD_SKIN* pSkin, const Uint8* basePtr);
	void decodeSkeleton(SMD_SKELETON* pSkeleton, const Uint8* basePtr);
	void decodeJoint(SMD_JOINT* pJoint, const Uint8* basePtr);

	Stray::Core::Graphics::VertexLayoutFormat toVLF(SMD_TYPE type);
	Stray::Core::Graphics::VertexLayoutType toVLT(const String& semantic);

	void makeResources();
	void makeMesh();
	void makeMaterial();
	void makeTexture();
	void makeSkeleton();
};

}
}

#endif